package com.zttek.photosShareProject.modules.service.share.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.zttek.photosShareProject.common.json.InfoVO;
import com.zttek.photosShareProject.common.json.UserVO;
import com.zttek.photosShareProject.common.json.VO;
import com.zttek.photosShareProject.common.myException.DBException;
import com.zttek.photosShareProject.modules.mapper.InfoMapper;
import com.zttek.photosShareProject.modules.model.Comment;
import com.zttek.photosShareProject.modules.model.Info;
import com.zttek.photosShareProject.modules.model.Share;
import com.zttek.photosShareProject.modules.model.User;
import com.zttek.photosShareProject.modules.service.login.IUserService;
import com.zttek.photosShareProject.modules.service.share.ICommentService;
import com.zttek.photosShareProject.modules.service.share.IInfoService;
import com.zttek.photosShareProject.modules.service.share.IShareService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: Y
 * Date: 2017-08-19
 * Time: 10:37
 */

@Service
public class InfoService implements IInfoService{

    @Autowired
    private InfoMapper infoMapper;

    @Autowired
    private IUserService userService;

    @Autowired
    private IShareService shareService;

    @Autowired
    private ICommentService commentService;

    @Transactional
    @Override
    public Info createSystemInfoForShare(Long toUserId, Long shareId, String content) throws Exception {
        Info info = fill(toUserId, null, content, SHARE, shareId, NOTICE);
//        infoInsert(info);
        infoMapper.insert(info);
        return info;
    }

    @Transactional
    @Override
    public Info createSystemInfoForComment(Long toUserId, Long commentId, String content) throws Exception {
        Info info = fill(toUserId, null, content, COMMENT, commentId, NOTICE);
//        infoInsert(info);
        infoMapper.insert(info);
        return info;
    }

    @Transactional
    @Override
    public Info createSystemInfoForNotice(Long toUserId, String content) throws Exception {
        Info info = fill(toUserId, null, content, NOTICE, null, NOTICE);
//        infoInsert(info);
        infoMapper.insert(info);
        return info;
    }

    @Transactional
    @Override
    public Info createUserInfoForShare(Long toUserId, Long fromUserId, Long shareId, Integer interact) throws Exception {
        Info info = fill(toUserId, fromUserId, null, SHARE, shareId, interact);
//        infoInsert(info);
        infoMapper.insert(info);
        return info;
    }

    @Transactional
    @Override
    public Info createUserInfoForComment(Long toUserId, Long fromUserId, Long commentId, Integer interact) throws Exception {
        Info info = fill(toUserId, fromUserId, null, COMMENT, commentId, interact);
//        infoInsert(info);
        infoMapper.insert(info);
        return info;
    }

    @Transactional
    @Override
    public Info createUserInfoForNotice(Long toUserId, Long fromUserId, Integer interact) throws Exception {
        Info info = fill(toUserId, fromUserId, null, NOTICE, null, interact);
//        infoInsert(info);
        infoMapper.insert(info);
        return info;
    }

    @Override
    public Integer countNewInfo(Long userId) throws Exception {
        EntityWrapper<Info> ew = new EntityWrapper<>();
        ew.where("valid = 1").and("to_user_id = {0}",userId).and("(status & 1) = 1");
        return infoMapper.selectCount(ew);
    }

    @Override
    public Page<Info> selectInfo(Page<Info> page, Long userId, Integer range) throws Exception {
        EntityWrapper<Info> ew = new EntityWrapper<>();
        ew.where("valid = 1");
        switch (range){
            case 1: ew.andNew("to_user_id = {0} and interact = 4", userId);break;
            case 2: ew.andNew("to_user_id = {0} and interact = 5", userId);break;
            default:
            case 0: ew.andNew("to_user_id = {0} and interact < 4", userId);break;
        }
//        List<Info> list = infoSelectPage(page, ew);
        List<Info> list = infoMapper.selectPage(page, ew);
        page.setRecords(list);
        return page;
    }

    @Override
    public Page<Info> selectAllSystemInfo(Page<Info> page) throws Exception {
        EntityWrapper<Info> ew = new EntityWrapper<>();
        ew.where("valid=1").and("interact=0").orderBy("createTime",false).orderBy("id");
        page.setRecords(infoMapper.selectPage(page,ew));
        return page;
    }

    @Transactional
    @Override
    public void read(List<Long> infoIds) throws Exception {
//        Info info = infoSelectById(infoId);
        EntityWrapper<Info> ew = new EntityWrapper<>();
        ew.where("valid=1").and("( status & 1 ) = 0").in("id",infoIds);
        Info info = new Info();
        info.setStatus(1);
        infoMapper.update(info, ew);
    }

    @Transactional
    @Override
    public void deleteInfo(Long infoId) throws Exception {
//        Info info = infoSelectById(infoId);
        Info info = infoMapper.selectById(infoId);
        info.setValid(0);
//        infoUpdate(info);
        infoMapper.updateById(info);
    }

    private InfoVO fillVO(Info info, boolean sys, String sysContent, UserVO informer, String attchType, Object attch, String interact, boolean read){
        InfoVO vo = new InfoVO();
        vo.setInfoId(info.getId());
        vo.setSys(sys);
        vo.setSysContent(sysContent);
        vo.setInformer(informer);
        vo.setAttachType(attchType);
        vo.setAttachVO(attch);
        vo.setInteract(interact);
        vo.setRead(read);
        return vo;
    }

    @Override
    public InfoVO info2VO(Info info) throws Exception {
        String sysContent = null, attchType = null;
        UserVO userVO = null;
        Object attch = null;
        String interact = null;
        boolean read = false, sys = false;
        switch (info.getInteract()){
            case InfoService.NOTICE: interact = InfoVO.NOTICE;break;
            case InfoService.PRAISE: interact = InfoVO.PRASIE;break;
            case InfoService.COLLECT: interact = InfoVO.COLLECT;break;
            case InfoService.STAR: interact = InfoVO.STAR;break;
            case InfoService.REPLY: interact = InfoVO.REPLY;break;
            default:
            case InfoService.AT: interact = InfoVO.AT;break;
        }

        switch (info.getTargetType()){
            case InfoService.COMMENT: {
                attchType = InfoVO.COMMENT;
                Comment comment = commentService.selectComment(info.getTargetId());
                attch = commentService.comment2VO(comment, null, true);
            }break;
            case InfoService.SHARE: {
                attchType = InfoVO.SHARE;
                Share share = shareService.selectShare(info.getTargetId());
                attch = shareService.share2VO(share, null, false);
            }break;
            default:
            case InfoService.NOTICE: {
                attchType = InfoVO.NOTICE;
                sysContent = info.getContent();
            }break;
        }
        if (info.getContent() != null){
            sys = true;
        }
        if ((info.getStatus() & 1) == 1)
            read = true;
        if (info.getFromUserId() != null){
            User user = userService.selectUserById(info.getFromUserId());
            userVO = userService.user2VO(user, null, false);
        }
        return fillVO(info, sys, sysContent, userVO, attchType, attch, interact, read);
    }

    @Override
    public List<InfoVO> info2VO(List<Info> infos) throws Exception {
        List<InfoVO> list = new ArrayList<>();
        for (Info info : infos){
            list.add(info2VO(info));
        }
        return list;
    }

    private Info fill(Long toUserId, Long fromUserId, String content, Integer type, Long targetId, Integer interact){
        Info info = new Info();
        Date date = new Date();
        info.setToUserId(toUserId);
        info.setFromUserId(fromUserId);
        info.setContent(content);
        info.setTargetType(type);
        info.setTargetId(targetId);
        info.setInteract(interact);
        info.setCreateTime(date);

        return info;
    }

    @Deprecated
    private Info infoSelectById(Long infoId){
        Info info = null;
        try {
            info = infoMapper.selectById(infoId);
        }catch (Exception e){
            e.printStackTrace();
            throw new DBException(DBException.INFO_SELECT_FAILURE);
        }
        return info;
    }

    @Deprecated
    private void infoInsert(Info info){
        try {
            infoMapper.insert(info);
        }catch (Exception e){
            e.printStackTrace();
            throw new DBException(DBException.INFO_INSERT_FAILURE);
        }
    }

    @Deprecated
    private void infoUpdate(Info info){
        try {
            infoMapper.updateById(info);
        }catch (Exception e){
            e.printStackTrace();
            throw new DBException(DBException.INFO_UPDATE_FAILURE);
        }
    }

    @Deprecated
    private List<Info> infoSelectPage(Page<Info> page, EntityWrapper<Info> ew){
        List<Info> infos = null;
        try {
            infos = infoMapper.selectPage(page, ew);
        }catch (Exception e){
            e.printStackTrace();
            throw new DBException(DBException.INFO_SELECT_FAILURE);
        }
        return infos;
    }
}
